package org.osgroup.project;

import org.osgroup.visitor.BaseVisitor;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 美食街类 - 管理多个餐馆
 * 继承自BaseProject，是游乐园中的一个特殊项目
 */
public class FoodStreet extends BaseProject {
    
    private final String foodStreetName;
    private final Map<String, Restaurant> restaurants;
    private final Lock lock;
    private boolean isOpen;
    private int totalVisitors;
    private int currentVisitorCount;
    
    /** 构造美食街 */
    public FoodStreet(String foodStreetName) {
        super();
        this.foodStreetName = foodStreetName;
        this.restaurants = new ConcurrentHashMap<>();
        this.lock = new ReentrantLock(true);
        this.isOpen = false;
        this.totalVisitors = 0;
        this.currentVisitorCount = 0;
        setProjectName(foodStreetName);
        setOk(true);
    }
    
    /** 构造美食街（带坐标） */
    public FoodStreet(String foodStreetName, double x, double y) {
        this(foodStreetName);
        setProjectX(x);
        setProjectY(y);
    }
    
    // ==================== 餐馆管理 ====================
    
    /** 添加餐馆到美食街 */
    public boolean addRestaurant(Restaurant restaurant) {
        lock.lock();
        try {
            if (restaurants.containsKey(restaurant.getRestaurantId())) {
                return false;
            }
            restaurants.put(restaurant.getRestaurantId(), restaurant);
            System.out.println("✅ 餐馆 " + restaurant.getRestaurantName() + " 已加入美食街");
            return true;
        } finally {
            lock.unlock();
        }
    }
    
    /** 从美食街移除餐馆 */
    public boolean removeRestaurant(String restaurantId) {
        lock.lock();
        try {
            Restaurant restaurant = restaurants.remove(restaurantId);
            if (restaurant == null) return false;
            
            restaurant.close();
            restaurant.clearBuffer();
            return true;
        } finally {
            lock.unlock();
        }
    }
    
    /** 根据ID获取餐馆 */
    public Restaurant getRestaurant(String restaurantId) {
        return restaurants.get(restaurantId);
    }
    
    /** 获取所有餐馆列表 */
    public List<Restaurant> getAllRestaurants() {
        return new ArrayList<>(restaurants.values());
    }
    
    /** 获取餐馆总数 */
    public int getRestaurantCount() {
        return restaurants.size();
    }
    
    // ==================== 营业控制 ====================
    
    /** 美食街开始营业 */
    public void openFoodStreet() {
        lock.lock();
        try {
            isOpen = true;
            System.out.println("\n🎊 " + foodStreetName + " 开始营业");
            for (Restaurant restaurant : restaurants.values()) {
                restaurant.open();
            }
            System.out.println("📢 共有 " + restaurants.size() + " 家餐馆营业\n");
        } finally {
            lock.unlock();
        }
    }
    
    /** 美食街打烊 */
    public void closeFoodStreet() {
        lock.lock();
        try {
            isOpen = false;
            System.out.println("\n🔒 " + foodStreetName + " 已打烊");
            for (Restaurant restaurant : restaurants.values()) {
                restaurant.close();
            }
        } finally {
            lock.unlock();
        }
    }
    
    // ==================== 初始化方法 ====================
    
    /** 快速初始化美食街(使用默认容量10) */
    public void initializeAndOpen() {
        initializeAndOpen(10,10);
    }
    
    /** 快速初始化美食街(创建川菜馆、粤菜馆、日料店) */
    public void initializeAndOpen(int bufferCapacity,int orderQueueSize) {
        System.out.println("\n🏗️ 初始化美食街 \"" + foodStreetName + "\"...\n");
        
        addRestaurant(createSichuanRestaurant(bufferCapacity,orderQueueSize));
        addRestaurant(createCantonRestaurant(bufferCapacity,orderQueueSize));
        addRestaurant(createJapaneseRestaurant(bufferCapacity,orderQueueSize));
        
        openFoodStreet();
        System.out.println("✅ 美食街初始化完成\n");
    }
    
    /** 创建川菜馆 */
    private Restaurant createSichuanRestaurant(int capacity,int orderQueueSize) {
        Restaurant r = new Restaurant("R001", "川菜馆", capacity, orderQueueSize);
        r.addMenuItem(new Restaurant.MenuItem("SC001", "宫保鸡丁", 38.0, 5000, "经典川菜"));
        r.addMenuItem(new Restaurant.MenuItem("SC002", "麻婆豆腐", 28.0, 4000, "麻辣鲜香"));
        r.addMenuItem(new Restaurant.MenuItem("SC003", "水煮鱼", 68.0, 8000, "鱼肉滑嫩"));
        r.addMenuItem(new Restaurant.MenuItem("SC004", "回锅肉", 42.0, 6000, "香味浓郁"));
        r.addMenuItem(new Restaurant.MenuItem("SC005", "夫妻肺片", 35.0, 3000, "口感丰富"));
        return r;
    }
    
    /** 创建粤菜馆 */
    private Restaurant createCantonRestaurant(int capacity,int orderQueueSize) {
        Restaurant r = new Restaurant("R002", "粤菜馆", capacity,orderQueueSize);
        r.addMenuItem(new Restaurant.MenuItem("GD001", "白切鸡", 48.0, 6000, "原汁原味"));
        r.addMenuItem(new Restaurant.MenuItem("GD002", "烧鹅", 88.0, 10000, "皮脆肉嫩"));
        r.addMenuItem(new Restaurant.MenuItem("GD003", "叉烧", 58.0, 7000, "甜而不腻"));
        r.addMenuItem(new Restaurant.MenuItem("GD004", "虾饺", 32.0, 4000, "晶莹剔透"));
        r.addMenuItem(new Restaurant.MenuItem("GD005", "肠粉", 25.0, 3000, "滑嫩爽口"));
        return r;
    }
    
    /** 创建日料店 */
    private Restaurant createJapaneseRestaurant(int capacity,int orderQueueSize) {
        Restaurant r = new Restaurant("R003", "日料店", capacity,orderQueueSize);
        r.addMenuItem(new Restaurant.MenuItem("JP001", "三文鱼刺身", 78.0, 3000, "入口即化"));
        r.addMenuItem(new Restaurant.MenuItem("JP002", "天妇罗", 68.0, 5000, "外酥里嫩"));
        r.addMenuItem(new Restaurant.MenuItem("JP003", "寿司拼盘", 88.0, 6000, "丰富美味"));
        r.addMenuItem(new Restaurant.MenuItem("JP004", "味噌汤", 18.0, 2000, "暖胃养生"));
        return r;
    }
    
    // ==================== 游客管理 ====================
    
    /** 游客进入美食街 */
    public void visitorEnter(BaseVisitor visitor) {
        lock.lock();
        try {
            if (!isOpen) {
                System.out.println("❌ 美食街已打烊,游客 " + visitor.getName() + " 无法进入");
                return;
            }
            currentVisitorCount++;
            totalVisitors++;
            System.out.println("👋 游客 " + visitor.getName() + " 进入美食街 | 当前: " + currentVisitorCount);
        } finally {
            lock.unlock();
        }
    }
    
    /** 游客离开美食街 */
    public void visitorLeave(BaseVisitor visitor) {
        lock.lock();
        try {
            currentVisitorCount--;
            System.out.println("👋 游客 " + visitor.getName() + " 离开美食街 | 当前: " + currentVisitorCount);
        } finally {
            lock.unlock();
        }
    }
    
    // ==================== 推荐系统 ====================
    
    /** 智能推荐餐馆(基于负载均衡,选择等待人数最少的餐馆) */
    public Restaurant recommendRestaurant() {
        List<Restaurant> openRestaurants = getOpenRestaurants();
        if (openRestaurants.isEmpty()) return null;
        
        Restaurant recommended = openRestaurants.get(0);
        int minWaiting = recommended.getWaitingVisitorCount();
        
        for (Restaurant restaurant : openRestaurants) {
            int waiting = restaurant.getWaitingVisitorCount();
            if (waiting < minWaiting) {
                minWaiting = waiting;
                recommended = restaurant;
            }
        }
        return recommended;
    }
    
    /** 随机选择一个营业中的餐馆 */
    public Restaurant getRandomRestaurant() {
        List<Restaurant> openRestaurants = getOpenRestaurants();
        if (openRestaurants.isEmpty()) return null;
        return openRestaurants.get(new Random().nextInt(openRestaurants.size()));
    }
    
    /** 获取所有营业中的餐馆 */
    public List<Restaurant> getOpenRestaurants() {
        List<Restaurant> openRestaurants = new ArrayList<>();
        for (Restaurant restaurant : restaurants.values()) {
            if (restaurant.isOpen()) {
                openRestaurants.add(restaurant);
            }
        }
        return openRestaurants;
    }
    
    /** 清空所有餐馆的缓冲区 */
    public void clearAllBuffers() {
        lock.lock();
        try {
            System.out.println("\n🧹 清空所有餐馆缓冲区...");
            for (Restaurant restaurant : restaurants.values()) {
                restaurant.clearBuffer();
            }
            System.out.println("✅ 缓冲区已清空\n");
        } finally {
            lock.unlock();
        }
    }
    
    // ==================== 统计信息 ====================
    
    /** 获取美食街统计信息 */
    public String getStatistics() {
        lock.lock();
        try {
            // 统计所有餐馆数据
            int totalMealsProduced = 0, totalMealsConsumed = 0;
            int totalWaitingChefs = 0, totalWaitingVisitors = 0;
            for (Restaurant r : restaurants.values()) {
                totalMealsProduced += r.getTotalMealsProduced();
                totalMealsConsumed += r.getTotalMealsConsumed();
                totalWaitingChefs += r.getWaitingChefCount();
                totalWaitingVisitors += r.getWaitingVisitorCount();
            }
            
            StringBuilder sb = new StringBuilder();
            sb.append("\n╔════════════════════════════════════════╗\n");
            sb.append(String.format("║  %s 统计信息\n", foodStreetName));
            sb.append("╠════════════════════════════════════════╣\n");
            sb.append(String.format("║  营业状态: %s\n", isOpen ? "✅ 营业中" : "🔒 已打烊"));
            sb.append(String.format("║  餐馆: %d 家 (营业 %d 家)\n", restaurants.size(), getOpenRestaurants().size()));
            sb.append(String.format("║  游客: 当前 %d 人 | 累计 %d 人\n", currentVisitorCount, totalVisitors));
            sb.append(String.format("║  出餐: %d 份 | 取餐: %d 份\n", totalMealsProduced, totalMealsConsumed));
            sb.append(String.format("║  等待: 厨师 %d 人 | 游客 %d 人\n", totalWaitingChefs, totalWaitingVisitors));
            sb.append("╚════════════════════════════════════════╝\n");
            return sb.toString();
        } finally {
            lock.unlock();
        }
    }
    
    /** 获取所有餐馆的详细状态 */
    public String getAllRestaurantStatus() {
        StringBuilder sb = new StringBuilder("\n【美食街所有餐馆状态】\n");
        for (Restaurant restaurant : restaurants.values()) {
            sb.append(restaurant.getStatus());
        }
        return sb.toString();
    }
    
    // ==================== Getter 方法 ====================
    
    public boolean isOpen() { return isOpen; }
    public String getFoodStreetName() { return foodStreetName; }
    public int getCurrentVisitorCount() { return currentVisitorCount; }
    public int getTotalVisitors() { return totalVisitors; }
    
    @Override
    public String toString() {
        return String.format("FoodStreet{name='%s', restaurants=%d, open=%s, visitors=%d/%d}", 
                             foodStreetName, restaurants.size(), isOpen, currentVisitorCount, totalVisitors);
    }
}
